package com.ruoyi.transaction.service.impl;

import com.ruoyi.common.entity.TransactionEntity.DTO.SpuSearchDTO;
import com.ruoyi.common.entity.TransactionEntity.VO.SpuVO;

import com.ruoyi.transaction.Repository.SpuSearchRepository;
import com.ruoyi.transaction.service.SpuSearchService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
// import org.elasticsearch.search.suggest.SuggestBuilder;
// import org.elasticsearch.search.suggest.SuggestBuilders;
// import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * SPU搜索服务实现
 */
@Slf4j
@Service
public class SpuSearchServiceImpl implements SpuSearchService {

    @Autowired
    private SpuSearchRepository spuSearchRepository;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<SpuSearchDTO> searchSpus(String keyword, int pageNum, int pageSize) {
        try {
            // 构建搜索查询
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 添加关键词搜索
            if (keyword != null && !keyword.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.multiMatchQuery(keyword)
                        .field("name", 3.0f)  // 商品名称权重最高
                        .field("brandName", 2.0f)  // 品牌名称权重次之
                        .field("categoryName", 1.5f)  // 分类名称权重
                        .field("description", 1.0f)  // 描述权重最低
                        .type(org.elasticsearch.index.query.MultiMatchQueryBuilder.Type.BEST_FIELDS));
            }

            // 只搜索激活且未删除的商品
            boolQuery.filter(QueryBuilders.termQuery("isActive", "1"));
            boolQuery.filter(QueryBuilders.termQuery("delFlag", "0"));

            // 构建搜索请求
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(boolQuery);
            searchSourceBuilder.from((pageNum - 1) * pageSize);
            searchSourceBuilder.size(pageSize);

            SearchRequest searchRequest = new SearchRequest("spu_index");
            searchRequest.source(searchSourceBuilder);

            // 执行搜索
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            // 解析结果
            List<SpuSearchDTO> results = new ArrayList<>();
            for (SearchHit hit : response.getHits().getHits()) {
                Map<String, Object> source = hit.getSourceAsMap();
                SpuSearchDTO spu = convertToSpuSearchDTO(source);
                results.add(spu);
            }

            return results;
        } catch (IOException e) {
            log.error("搜索商品失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<String> getSearchSuggestions(String keyword) {
        try {
            if (keyword == null || keyword.trim().isEmpty()) {
                return new ArrayList<>();
            }

            // 构建搜索查询，只根据商品名称搜索
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            boolQuery.must(QueryBuilders.matchQuery("name", keyword));
            boolQuery.filter(QueryBuilders.termQuery("isActive", "1"));
            boolQuery.filter(QueryBuilders.termQuery("delFlag", "0"));

            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.query(boolQuery);
            searchSourceBuilder.size(10); // 最多返回10条建议

            SearchRequest searchRequest = new SearchRequest("spu_index");
            searchRequest.source(searchSourceBuilder);

            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            // 只提取商品名称作为建议，并去重
            Set<String> suggestions = new LinkedHashSet<>();
            for (SearchHit hit : response.getHits().getHits()) {
                Map<String, Object> source = hit.getSourceAsMap();
                String name = (String) source.get("name");
                if (name != null) {
                    suggestions.add(name);
                }
                if (suggestions.size() >= 10) {
                    break;
                }
            }

            return new ArrayList<>(suggestions);
        } catch (IOException e) {
            log.error("获取搜索建议失败", e);
            return new ArrayList<>();
        }
    }


    @Override
    public void syncSpuToES(Long spuId) {
        try {
            // 从数据库查询SPU信息
            String sql = "SELECT " +
                    "s.id, " +
                    "s.name, " +
                    "s.brand_name as brandName, " +
                    "s.unit, " +
                    "s.description, " +
                    "s.image_urls as imageUrls, " +
                    "s.barcode, " +
                    "s.is_active as isActive, " +
                    "s.del_flag as delFlag, " +
                    "s.category_id as categoryId, " +
                    "c.name as categoryName, " +
                    "s.create_time as createTime, " +
                    "s.update_time as updateTime " +
                    "FROM spu s " +
                    "LEFT JOIN category c ON s.category_id = c.id " +
                    "WHERE s.id = ? AND s.del_flag = '0'";

            List<Map<String, Object>> results = jdbcTemplate.queryForList(sql, spuId);

            if (!results.isEmpty()) {
                Map<String, Object> row = results.get(0);
                SpuSearchDTO spu = convertToSpuSearchDTO(row);

                // 构建搜索建议
                buildSuggestions(spu);

                // 保存到ES
                spuSearchRepository.save(spu);
                log.info("同步SPU到ES成功，SPU ID: {}", spuId);
            } else {
                // SPU不存在或已删除，从ES中删除
                spuSearchRepository.deleteById(spuId);
                log.info("从ES删除SPU，SPU ID: {}", spuId);
            }
        } catch (Exception e) {
            log.error("同步SPU到ES失败，SPU ID: {}", spuId, e);
        }
    }

    @Override
    public void batchSyncSpusToES() {
        try {
            log.info("开始批量同步SPU到ES");

            // 获取所有SPU数据
            String sql = "SELECT " +
                    "s.id, " +
                    "s.name, " +
                    "s.brand_name as brandName, " +
                    "s.unit, " +
                    "s.description, " +
                    "s.image_urls as imageUrls, " +
                    "s.barcode, " +
                    "s.is_active as isActive, " +
                    "s.del_flag as delFlag, " +
                    "s.category_id as categoryId, " +
                    "c.name as categoryName, " +
                    "s.create_time as createTime, " +
                    "s.update_time as updateTime " +
                    "FROM spu s " +
                    "LEFT JOIN category c ON s.category_id = c.id " +
                    "WHERE s.del_flag = '0' " +
                    "ORDER BY s.create_time DESC";

            List<Map<String, Object>> results = jdbcTemplate.queryForList(sql);

            List<SpuSearchDTO> spus = new ArrayList<>();
            for (Map<String, Object> row : results) {
                SpuSearchDTO spu = convertToSpuSearchDTO(row);
                buildSuggestions(spu);
                spus.add(spu);
            }

            // 批量保存到ES
            spuSearchRepository.saveAll(spus);

            log.info("批量同步SPU到ES完成，共同步 {} 个SPU", spus.size());
        } catch (Exception e) {
            log.error("批量同步SPU到ES失败", e);
            throw e;
        }
    }

    @Override
    public void deleteSpuFromES(Long spuId) {
        try {
            spuSearchRepository.deleteById(spuId);
            log.info("从ES删除SPU成功，SPU ID: {}", spuId);
        } catch (Exception e) {
            log.error("从ES删除SPU失败，SPU ID: {}", spuId, e);
        }
    }

    @Override
    public void rebuildIndex() {
        try {
            log.info("开始重建ES索引");

            // 删除现有索引
//            if (elasticsearchRestTemplate.indexExists("spu_index")) {
//                elasticsearchRestTemplate.indexDelete("spu_index");
//            }
//
//            // 重新创建索引
//            elasticsearchRestTemplate.indexCreate("spu_index");

            // 批量同步数据
            batchSyncSpusToES();

            log.info("重建ES索引完成");
        } catch (Exception e) {
            log.error("重建ES索引失败", e);
            throw e;
        }
    }

    /**
     * 将数据库行转换为SpuSearchDTO
     */
    private SpuSearchDTO convertToSpuSearchDTO(Map<String, Object> row) {
        SpuSearchDTO spu = new SpuSearchDTO();
        spu.setId(((Number) row.get("id")).longValue());
        spu.setName((String) row.get("name"));
        spu.setBrandName((String) row.get("brandName"));
        spu.setUnit((String) row.get("unit"));
        spu.setDescription((String) row.get("description"));
        spu.setImageUrls((String) row.get("imageUrls"));
        spu.setBarcode((String) row.get("barcode"));
        spu.setIsActive((String) row.get("isActive"));
        spu.setDelFlag((String) row.get("delFlag"));

        if (row.get("categoryId") != null) {
            spu.setCategoryId(((Number) row.get("categoryId")).longValue());
        }
        spu.setCategoryName((String) row.get("categoryName"));

        if (row.get("createTime") != null) {
            spu.setCreateTime((java.sql.Timestamp) row.get("createTime"));
        }
        if (row.get("updateTime") != null) {
            spu.setUpdateTime((java.sql.Timestamp) row.get("updateTime"));
        }

        return spu;
    }

    /**
     * 构建搜索建议
     */
    private void buildSuggestions(SpuSearchDTO spu) {
        List<String> suggestions = new ArrayList<>();

        if (spu.getName() != null) {
            suggestions.add(spu.getName());
        }
        if (spu.getBrandName() != null) {
            suggestions.add(spu.getBrandName());
        }
        if (spu.getCategoryName() != null) {
            suggestions.add(spu.getCategoryName());
        }

        spu.setSuggestions(suggestions);
    }
}